package org.l.qiao;

import org.bson.types.ObjectId;
import org.l.qiao.annotation.Key;
import org.l.qiao.base.LType;
import org.l.qiao.util.ClusterUtil;

import java.io.Serializable;
import java.util.*;

/**
 * Created by 严秋旺 on 2015/1/6.
 * <p/>
 * 数据簇
 */
public class Cluster implements Map<String, Object>, Serializable {

    private LinkedHashMap<String, Object> map;
    /**
     * EL表达式键名分割符
     */
    private static final String ELKEY_SPLIT = "\\.";

    /**
     * 属性：ID，主键
     */
    @Key(keyType = KeyType.MapKey, valueType = LType.LTYPE_STRING, check = Validate.OBJECTID, nullable = true)
    public static final String ID = "_id";
    /**
     * 属性：创建时间
     */
    public static final String CREATED = "created";

    public Cluster() {
        map = new LinkedHashMap();
    }

    /**
     * 从Map对象初始化Cluster
     *
     * @param map 初始Map对象
     */
    public Cluster(Map<String, Object> map) {
        this.map = new LinkedHashMap(map);
    }

    /**
     * 从一对键值初始化Cluster
     *
     * @param key    键名
     * @param object 值
     */
    public Cluster(String key, Object object) {
        map = new LinkedHashMap();
        put(key, object);
    }

    public Object setId(String id) {
        return this.put(ID, new ObjectId(id));
    }

    public String setId() {
        ObjectId oid = new ObjectId();
        this.put(ID, oid);
        return oid.toString();
    }

    public String getId() {
        return getString(ID, "");
    }

    public String getString(String key) {
        return getString(key, null);
    }

    public String getString(String key, String defval) {
        Object object = get(key);

        if (object != null) {
            return object.toString();
        } else {
            return defval;
        }
    }

    public int getInteger(String key) {
        return getInteger(key, 0);
    }

    public int getInteger(String key, int defval) {
        Object object = get(key);

        if (object != null) {
            if (object instanceof Integer) {
                return (Integer) object;
            } else {
                try {
                    return Integer.parseInt(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public long getLong(String key) {
        return getLong(key, 0l);
    }

    public long getLong(String key, long defval) {
        Object object = get(key);

        if (object != null) {
            if (object instanceof Long) {
                return (Long) object;
            } else {
                try {
                    return Long.parseLong(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public float getFloat(String key) {
        return getFloat(key, 0l);
    }

    public float getFloat(String key, float defval) {
        Object object = get(key);

        if (object != null) {
            if (object instanceof Float) {
                return (Float) object;
            } else {
                try {
                    return Float.parseFloat(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public double getDouble(String key) {
        return getDouble(key, 0l);
    }

    public double getDouble(String key, double defval) {
        Object object = get(key);

        if (object != null) {
            if (object instanceof Double) {
                return (Double) object;
            } else {
                try {
                    return Double.parseDouble(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public boolean getBoolean(String key) {
        return getBoolean(key, false);
    }

    public boolean getBoolean(String key, boolean defval) {
        Object object = get(key);

        if (object != null) {
            if (object instanceof Boolean) {
                return (Boolean) object;
            } else {
                try {
                    return Boolean.parseBoolean(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public Date getDate(String key) {
        return getDate(key, null);
    }

    public Date getDate(String key, Date defval) {
        Object object = get(key);

        if (object != null) {
            return (Date) object;
        } else {
            return defval;
        }
    }

    public List<Object> getList(String key) {
        return getList(key, null);
    }

    public List<Object> getList(String key, ArrayList defval) {
        Object object = get(key);

        if (object != null) {
            return (ArrayList<Object>) object;
        } else {
            return defval;
        }
    }

    public Map<String, Object> getMap(String key) {
        return getMap(key, null);
    }

    public Map<String, Object> getMap(String key, Map defval) {
        Object object = get(key);

        if (object != null) {
            return (Map<String, Object>) object;
        } else {
            return defval;
        }
    }

    public Cluster getCluster(String key) {
        return getCluster(key, null);
    }

    public Cluster getCluster(String key, Cluster defval) {
        Object object = get(key);

        if (object != null) {
            Map<String, Object> map = (Map<String, Object>) object;
            return new Cluster(map);
        } else {
            return defval;
        }
    }

    /**
     * 根据EL表达式获取键值
     *
     * @param elKey EL表达式
     * @return 键值
     */
    public Object elget(String elKey) {
        return ClusterUtil.get(this, elKey);
    }

    /**
     * 根据EL表达式获取键值
     *
     * @param elKey EL表达式
     * @param value 键值
     * @return EL表达式对应的旧值
     */
    public Object elput(String elKey, Object value) {
        return ClusterUtil.put(this, elKey, value);
    }

    /**
     * 根据EL表达式添加元素
     *
     * @param elKey EL表达式
     * @param value 值
     * @return
     */
    public boolean eladd(String elKey, Object value) {
        return ClusterUtil.add(this, elKey, value);
    }


    public String elgetString(String key) {
        return elgetString(key, null);
    }

    public String elgetString(String key, String defval) {
        Object object = elget(key);

        if (object != null) {
            return object.toString();
        } else {
            return defval;
        }
    }

    public int elgetInteger(String key) {
        return elgetInteger(key, 0);
    }

    public int elgetInteger(String key, int defval) {
        Object object = elget(key);

        if (object != null) {
            if (object instanceof Integer) {
                return (Integer) object;
            } else {
                try {
                    return Integer.parseInt(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public long elgetLong(String key) {
        return elgetLong(key, 0l);
    }

    public long elgetLong(String key, long defval) {
        Object object = elget(key);

        if (object != null) {
            if (object instanceof Long) {
                return (Long) object;
            } else {
                try {
                    return Long.parseLong(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public float elgetFloat(String key) {
        return elgetFloat(key, 0l);
    }

    public float elgetFloat(String key, float defval) {
        Object object = elget(key);

        if (object != null) {
            if (object instanceof Float) {
                return (Float) object;
            } else {
                try {
                    return Float.parseFloat(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public double elgetDouble(String key) {
        return elgetDouble(key, 0l);
    }

    public double elgetDouble(String key, double defval) {
        Object object = elget(key);

        if (object != null) {
            if (object instanceof Double) {
                return (Double) object;
            } else {
                try {
                    return Double.parseDouble(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public boolean elgetBoolean(String key) {
        return elgetBoolean(key, false);
    }

    public boolean elgetBoolean(String key, boolean defval) {
        Object object = elget(key);

        if (object != null) {
            if (object instanceof Boolean) {
                return (Boolean) object;
            } else {
                try {
                    return Boolean.parseBoolean(object.toString());
                } catch (Exception e) {
                    return defval;
                }
            }
        } else {
            return defval;
        }
    }

    public Date elgetDate(String key) {
        return elgetDate(key, null);
    }

    public Date elgetDate(String key, Date defval) {
        Object object = elget(key);

        if (object != null) {
            return (Date) object;
        } else {
            return defval;
        }
    }

    public List<Object> elgetList(String key) {
        return elgetList(key, null);
    }

    public List<Object> elgetList(String key, ArrayList defval) {
        Object object = elget(key);

        if (object != null) {
            return (ArrayList<Object>) object;
        } else {
            return defval;
        }
    }

    public Map<String, Object> elgetMap(String key) {
        return elgetMap(key, null);
    }

    public Map<String, Object> elgetMap(String key, Map defval) {
        Object object = elget(key);

        if (object != null) {
            return (Map<String, Object>) object;
        } else {
            return defval;
        }
    }

    public Cluster elgetCluster(String key) {
        return elgetCluster(key, null);
    }

    public Cluster elgetCluster(String key, Cluster defval) {
        Object object = elget(key);

        if (object != null) {
            Map<String, Object> map = (Map<String, Object>) object;
            return new Cluster(map);
        } else {
            return defval;
        }
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public Object get(Object key) {
        return map.get(key);
    }

    @Override
    public Object put(String key, Object value) {
        return map.put(key, value);
    }

    @Override
    public Object remove(Object key) {
        return map.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ?> m) {
        map.putAll(m);
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public Set<String> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<Object> values() {
        return map.values();
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return map.entrySet();
    }

    public Object clone(){
        LinkedHashMap newMap = (LinkedHashMap)map.clone();
        return new Cluster(newMap);
    }
}
